<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>关键问题</title>
</head>
<body>
  <script>
    // 1、如何改变 Promsie 对象的状态？
    // 1) resolve(value): pending => resolved
    // 2) reject(reason): pending => rejected
    // 3) throw ... 或 throw new Error(): pending => rejected

    // 2、一个 Promise 对象指定多个[成功]/[失败]的回调函数，都会调用吗？
    // 答：指定的多个回调都会调用。
    const p2 = Promise.resolve('p2 执行成功');
    p2.then(value => {
      console.log('p2 的第一个回调');
    }, reason => {});
    p2.then(value => {
      console.log('p2 的第二个回调');
    }, reason => {});

    // 3、改变 Promise 状态和指定回调函数谁先谁后？
    // 答：不一定，有时候先改变状态，有时候先指定回调，一般先指定回调再改变状态。
    // 同步任务时先改变状态，异步任务时先指定回调，一般为异步任务。
    // 当延长更长时间调用 then() 时，先改变状态再指定回调
    const p3 = new Promise((resolve, reject) => {
      resolve('p3 执行成功');
    });
    setTimeout(() => {
      p3.then(value => {
        console.log(value);
      }, reason => {});
    }, 1000);
    // 什么时候指定回调才能拿到数据？
    // 1) 如果先指定回调，那状态发生改变时拿到数据。2) 如果先改变状态，那么指定回调时直接拿到数据

    // 4、Promise.then() 返回的新 Promise 的结果状态由什么决定？
    // 简单表达：由 then() 指定回调的返回值决定。
    // 详细表达：1) 返回非 Promise 对象，则新 Promise 对象状态为[成功]，结果为返回值。PS: 无返回值默认状态为[成功]，返回值为 undefined
    //         2) 返回 Promise 对象，则新 Promise 对象状态结果均为返回的 Promise 的状态结果
    //         3) 抛出错误，则新 Promise 对象状态为[失败]，结果为抛出的值
    // 返回非 Promise 对象
    const p4_1 = Promise.resolve('p4_1 执行成功');
    const p4_1_result = p4_1.then(value => {
      return value;
    }, reason => {});
    console.log('p4_1_result:', p4_1_result); // 返回 Promise 状态为[成功]，结果为返回值
    // 抛出错误
    const p4_2 = Promise.resolve('p4_2 执行成功');
    const p4_2_result = p4_2.then(value => {
      throw 'p4_2 出错啦';
    });
    console.log('p4_2_result:', p4_2_result); // 返回 Promise 状态为[失败]，结果为抛出的值
    // 返回成功的 Promise 对象
    const p4_3 = Promise.resolve('p4_3 执行成功');
    const p4_3_result = p4_3.then(value => {
      return Promise.resolve(value);
    }, reason => {});
    console.log('p4_3_result:', p4_3_result); // 返回 Promise 状态为[成功]，结果为返回 Promise 对象的结果
    // 返回失败的 Promise 对象
    const p4_4 = Promise.resolve('p4_4 执行成功');
    const p4_4_result = p4_4.then(value => {
      return Promise.reject('p4_4 执行失败');
    }, reason => {});
    console.log('p4_4_result:', p4_4_result); // 返回 Promise 状态为[失败]，结果为返回 Promise 对象的结果

    // 5、Promise 如何串连多个操作任务？
    // 答：Promsie 的 then() 方法返回一个新的 Promise 对象，由此形成链式调用
    //    通过 then() 的链式调用串连多个同步/异步任务
    const p5 = Promise.resolve('p5 执行成功');
    // 下面省略了失败的回调
    p5.then(value => {
      console.log('p5_1:', value); // 控制台输出 “p5 执行成功“
      return Promise.resolve('第一次链式调用');
    }).then(value => {
      console.log('p5_2:', value); // 控制台输出 “第一次链式调用”
    }).then(value => {
      console.log('p5_3:', value); // 由于上次 then() 方法没有返回值，所以结果为默认的 undefined
    });

    // 6、Promise 异常穿透
    // 当使用 Promise 的 then() 方法进行链式调用的时候，可以在最后指定失败的回调，前面任何操作出现了异常，都会传到最后的回调进行处理
    const p6 = Promise.reject('p6 第一次失败');
    p6.then(value => {
      // 这里不执行
    }).catch(reason => {{
      console.log('p6 失败', reason); // 在这里捕获第一次失败
    }});

    // 7、中断 Promise 链：使用 Promsie 的 then() 方法链式调用时，在中间中断，不执行后面的回调函数
    // 方法：通过在回调函数中返回一个状态为 pending的 Promsie 对象
    const p7 = Promise.resolve('p7 执行成功');
    p7.then(value => {
      console.log('p7:', value);
      return new Promise(() => {}); // 返回状态为 pending 的 Promsie 对象
    }).then(value => {
      console.log('成功回调，不执行');
    }, reason => {
      console.log('失败回调，不执行');
    });
  </script>
</body>
</html>